﻿using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;

using ButtonBuilder.Plugin;

using WPFColorPickerLib;
using WPFFontPickerLib;

namespace ButtonBuilder.Controls
{
    /// <summary>
    /// Interaction logic for MediaButton.xaml
    /// </summary>
    public partial class MediaButton : Button
    {
        private static readonly string[] SUPPORTTED_AUDIO_FORMATS = { "mp3" };

        private static readonly string[] SUPPORTTED_VIDEO_FORMATS = { "3gp", "wmv", "mp4", "avi" };

        private static readonly string DEFAULT_CAPTION = "New Media Button";

        #region Constructors
        /// <summary>
        /// Default constructor
        /// </summary>
        public MediaButton() : base()
        {
            Caption = DEFAULT_CAPTION;

            InitializeComponent();
        }

        #endregion

        #region Properties
        private bool IsPlaying { get; set; }

        public override Border Border { get { return ButtonBorder; } }
        #endregion

        #region Methods
        private void LoadMediaFile(string filePath)
        {
            IsPlaying = false;

            MediaPlayer.ScrubbingEnabled = SUPPORTTED_VIDEO_FORMATS
                .Contains(System.IO.Path.GetExtension(filePath).TrimStart('.'));
            MediaPlayer.Source = new Uri(filePath);
                       
            btnPlay.IsEnabled = true;
            btnHome.IsEnabled = true;
            btnPlay.Content = "Play";
            
            MediaPlayer.Play();
            MediaPlayer.Pause();
        }

        private void Play()
        {
            if (IsPlaying)
            {
                IsPlaying = false;
                btnPlay.Content = "Play";

                CaptionAdorner.Visibility = System.Windows.Visibility.Visible;
                MediaPlayer.Pause();
            }
            else
            {
                IsPlaying = true;
                btnPlay.Content = "Pause";

                if (IsVideoFile(MediaPlayer.Source.ToString()))
                    CaptionAdorner.Visibility = System.Windows.Visibility.Collapsed;
                
                MediaPlayer.Play();
            }
        }

        private void Home()
        {
            IsPlaying = false;
            btnPlay.Content = "Play";

            CaptionAdorner.Visibility = System.Windows.Visibility.Visible;

            MediaPlayer.Stop();
            MediaPlayer.Play();
            MediaPlayer.Pause();
        }

        private bool IsVideoFile(string filename)
        {
            string extention = System.IO.Path.GetExtension(filename).Trim('.');
            return SUPPORTTED_VIDEO_FORMATS.Contains(extention);
        }
        #endregion

        #region Overrides
        public override Data.Button GetData()
        {
            Data.Button data = base.GetData();

            if (CaptionAdorner != null)
            {
                data.Font = new Data.ButtonFont()
                {
                    Name = CaptionAdorner.CaptionControl.FontFamily.Source,
                    Size = CaptionAdorner.CaptionControl.FontSize,
                    Weight = CaptionAdorner.CaptionControl.FontWeight.ToOpenTypeWeight(),
                    Color = CaptionAdorner.CaptionControl.Foreground.ToString()
                };
            }

            if (ButtonImageBackground.Background as ImageBrush != null)
            {
                data.ImageVisible = true;
                data.ImagePath = ((ImageBrush)ButtonImageBackground.Background).ImageSource.ToString();
            }
            else if (ButtonImageBackground.Background as SolidColorBrush != null)
            {
                data.Background = ButtonImageBackground.Background.ToString();
            }

            if (MediaPlayer.Source != null)
            {
                data.MediaPath = MediaPlayer.Source.ToString();
            }

            return data;
        }

        public override void SetData(Data.Button data)
        {
            base.SetData(data);

            //NOTE: Font applied when CaptionAdorner is created.

            if (data.ImageVisible)
            {
                ButtonImageBackground.Background = new ImageBrush(new BitmapImage(new Uri(data.ImagePath)));
            }
            else
            {
                ButtonImageBackground.Background = new SolidColorBrush((Color)ColorConverter.ConvertFromString(data.Background));
            }

            if (data.MediaPath != null)
            {
                LoadMediaFile(data.MediaPath);
            }
        }

        protected override void OnClick(ActionEventArgs e)
        {
            base.OnClick(e);

            if (MediaPlayer.Source != null)
                Play();
        }

        protected override void ApplyPressedTheme(bool pressed)
        {
            base.ApplyPressedTheme(pressed);

            ButtonBorder.BorderThickness = new Thickness(ButtonBorder.BorderThickness.Top +
                (pressed ? 1 : -1)); ;
        }

        public override void Dispose()
        {
            Home();

            base.Dispose();
        }
        #endregion

        #region ContextMenu Handlers
        private void itmRemove_Click(object sender, RoutedEventArgs e)
        {
            Dispatcher.BeginInvoke(new System.Threading.ThreadStart(() =>
            {
                ParentWindow.RemovePageButton(this);
            }));
        }

        private void itmCaptionText_Click(object sender, RoutedEventArgs e)
        {
            string userText = InputDialog.ShowDialog(ParentWindow, "Caption:", "Edit Caption",
                 CaptionAdorner.CaptionControl.Text, true);

            if (!string.IsNullOrWhiteSpace(userText))
            {
                Caption = userText;
                CaptionAdorner.Text = userText;
                AdornerLayer.GetAdornerLayer(MediaPanel).Update();

                OnPropertyChanged("Caption");
            }
        }

        private void itmCaptionFont_Click(object sender, RoutedEventArgs e)
        {
            FontChooser fontChooser = new FontChooser();
            fontChooser.Owner = Window.GetWindow(this);

            fontChooser.SetPropertiesFromObject(CaptionAdorner.CaptionControl);
            fontChooser.PreviewSampleText = CaptionAdorner.CaptionControl.Text;

            if (fontChooser.ShowDialog().Value)
            {
                fontChooser.ApplyPropertiesToObject(CaptionAdorner.CaptionControl);
                AdornerLayer.GetAdornerLayer(MediaPanel).Update();

                Font = new Data.ButtonFont()
                {
                    Name = CaptionAdorner.CaptionControl.FontFamily.Source,
                    Size = CaptionAdorner.CaptionControl.FontSize,
                    Weight = CaptionAdorner.CaptionControl.FontWeight.ToOpenTypeWeight()
                };

                OnPropertyChanged("Font");
            }
        }

        private void itmCaptionColor_Click(object sender, RoutedEventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            colorDialog.Owner = Window.GetWindow(this);

            if ((bool)colorDialog.ShowDialog())
            {
                CaptionAdorner.CaptionControl.Foreground = new SolidColorBrush(colorDialog.SelectedColor);

                OnPropertyChanged("CaptionColor");
            }
        }

        private void itmBackgroundColor_Click(object sender, RoutedEventArgs e)
        {
            ColorDialog colorDialog = new ColorDialog();
            colorDialog.Owner = Window.GetWindow(this);

            if ((bool)colorDialog.ShowDialog())
            {
                ButtonImageBackground.Background = new SolidColorBrush(colorDialog.SelectedColor);
                OnPropertyChanged("Background");
            }
        }

        private void itmBackgroundPicture_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            dlg.DefaultExt = ".png";
            dlg.Filter = "Image (.png)|*.png";

            if (dlg.ShowDialog(Window.GetWindow(this)) == true)
            {
                string imagePath = dlg.FileName;
                ButtonImageBackground.Background = new ImageBrush(new BitmapImage(new Uri(imagePath)));
                OnPropertyChanged("Image");
            }
        }

        private void itmLower_Click(object sender, RoutedEventArgs e)
        {
            Page.LowerButton(this);
            OnPropertyChanged("ZIndex");
        }

        private void itmRaise_Click(object sender, RoutedEventArgs e)
        {
            Page.RaiseButton(this);
            OnPropertyChanged("ZIndex");
        }

        private void itmOpenFile_Click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
            
            dlg.Filter = "Video Files|";
            dlg.Filter += SUPPORTTED_VIDEO_FORMATS.Select(f => string.Format("*.{0}", f))
                .Aggregate((p, q) => p + ";" + q);
            dlg.Filter += "|Audio Files|";
            dlg.Filter += SUPPORTTED_AUDIO_FORMATS.Select(f => string.Format("*.{0}", f))
                .Aggregate((p, q) => p + ";" + q);
            
            dlg.FilterIndex = 0;

            if (dlg.ShowDialog(Window.GetWindow(this)) == true)
            {
                LoadMediaFile(dlg.FileName);
                OnPropertyChanged("MediaPath");

                string filename = System.IO.Path.GetFileName(dlg.FileName);

                if (!filename.Equals(Caption))
                {
                    bool updateCaption = MessageBox.Show(
                        "Would you like to automatically update the button's " +
                        "caption with the name of the media file?", 
                        "Update Button Caption?", 
                        MessageBoxButton.YesNo, 
                        MessageBoxImage.Question) == MessageBoxResult.Yes;

                    if (updateCaption)
                    {
                        Caption = filename;
                        CaptionAdorner.Text = filename;
                        AdornerLayer.GetAdornerLayer(MediaPanel).Update();

                        OnPropertyChanged("Caption");
                    }
                }
            }
        }
        #endregion

        #region Focus Helpers
        private void TextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (EnterKeyDown)
                return;

            if (e.Key == Key.Enter)
            {
                EnterKeyDown = true;
                base.OnMouseLeftButtonDown(null);
            }
        }

        private void TextBox_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter)
            {
                EnterKeyDown = false;
                base.OnMouseLeftButtonUp(null);
            }
        }

        private void TextBox_GotFocus(object sender, RoutedEventArgs e)
        {
            OnGotFocus(new RoutedEventArgs(GotFocusEvent, this));
        }
        #endregion

        #region Media Player Handlers
        private void btnPlay_Click(object sender, RoutedEventArgs e)
        {
            Play();
        }

        private void btnHome_Click(object sender, RoutedEventArgs e)
        {
            Home();
        }

        private void MediaPlayer_MediaEnded(object sender, RoutedEventArgs e)
        {
            MediaPlayer.Stop();
            MediaPlayer.Play();
        }
        #endregion

        #region Caption Helpers
        private void MediaPanel_Loaded(object sender, RoutedEventArgs e)
        {
            if (CaptionAdorner == null)
            {
                CaptionAdorner = new ButtonCaption(this, MediaPanel, Caption);

                if (Font != null)
                {
                    CaptionAdorner.CaptionControl.FontFamily = new FontFamily(Font.Name);
                    CaptionAdorner.CaptionControl.FontSize = Font.Size;
                    CaptionAdorner.CaptionControl.FontWeight = FontWeight.FromOpenTypeWeight(Font.Weight);
                    CaptionAdorner.CaptionControl.Foreground = new SolidColorBrush(
                        (Color)ColorConverter.ConvertFromString(Font.Color));
                }

                AdornerLayer.GetAdornerLayer(MediaPanel).Add(CaptionAdorner);
            }
        }
        #endregion
      
    }
}
